<template>
  <div
    class="chart_data_preview"
    :style="{
      border: border ? `1px solid var(--default)` : 'none',
    }"
  >
    <div class="chart_operate">
      <el-tooltip effect="dark" content="数据视图" placement="top">
        <el-icon size="18" @click="showTable = true">
          <Document />
        </el-icon>
      </el-tooltip>
    </div>
    <transition name="fade">
      <div class="chart_table_data" v-show="showTable">
        <h3 class="chart_table_title">数据视图</h3>
        <table
          style="display: block; width: 100%; text-align: center"
          class="chart_table"
          :border="true"
          cellspacing="0"
        >
          <thead>
            <tr>
              <td
                v-for="(head, index) in headerArr"
                :title="head"
                :key="'head' + index"
              >
                {{ head }}
              </td>
            </tr>
          </thead>
          <tbody class="tbody" ref="tbodyRef">
            <tr v-for="(line, index) in tableData" :key="'line' + index">
              <td
                v-for="(_, i) in headerArr"
                :key="'line' + index + '-col' + i"
                :title="line[i]"
              >
                {{ line[i] }}
              </td>
            </tr>
          </tbody>
        </table>
        <div class="chart_table_operate">
          <div class="chart_table_operate_btn" @click="showTable = false">
            关闭
          </div>
          <div class="chart_table_operate_btn" @click="downloadData">下载</div>
        </div>
      </div>
    </transition>
    <div class="chart_box" ref="chartRef"></div>
  </div>
</template>

<script setup>
import { Document } from "@element-plus/icons-vue";
import { exportExcel } from "@/utils";
import * as echarts from "echarts";
import { shallowRef, nextTick, ref } from "vue";

const props = defineProps({
  border: {
    type: Boolean,
    default: false,
  },
  fileName: {
    type: String,
    default: "图表数据",
  },
  option: {
    type: Object,
  },
});

const headerArr = ref([]);
const tableData = ref([]);
const showTable = ref(false);
const optionValue = ref({});
const unitArr = ref([]);
const tbodyRef = ref();

const chartRef = ref(null);
const myChart = shallowRef(null);

// 将option数据转化为table数据
const getChartOption = (option) => {
  optionValue.value = option;
  const xAxis = option.xAxis.data;
  if (Array.isArray(option.yAxis)) {
    unitArr.value = option.yAxis.map((v) => v.name);
  } else {
    unitArr.value = [option.yAxis.name];
  }
  const series = Array.isArray(option.series) ? option.series : [option.series];
  headerArr.value = [
    "时间",
    ...series.map((item) => {
      const unitIndex = item.yAxisIndex || 0;
      const unit = unitArr.value[unitIndex];
      return unit ? `${item.name}（${unit}）` : item.name;
    }),
  ];
  tableData.value = xAxis.map((item, index) => [
    item,
    ...series.map((v) => v.data[index]),
  ]);
};

// 下载数据视图
const downloadData = () => {
  const thead = headerArr.value.map((item, index) => {
    return {
      props: index === 0 ? "time" : `data${index}`,
      name: item,
    };
  });
  const chartData = tableData.value.map((item) => {
    const rowData = {};
    item.forEach((v, i) => {
      if (i === 0) rowData.time = v;
      rowData[`data${i}`] = v;
    });
    return rowData;
  });

  exportExcel(thead, chartData, props.fileName);
};

// 创建echarts图表
const createChart = () => {
  if (myChart.value) {
    disposeEcharts();
    initEcharts();
  } else {
    initEcharts();
  }
  showTable.value = false;
  nextTick(() => {
    setOption(props.option);
    getChartOption(props.option);
  });
};

// 初始化echarts图表
const initEcharts = () => {
  if (chartRef.value) {
    myChart.value = echarts.init(chartRef.value);
    window.addEventListener("resize", resizeChart);
  }
};

// 销毁echarts图表
const disposeEcharts = () => {
  window.removeEventListener("resize", resizeChart);
  myChart.value?.dispose();
  myChart.value = null;
};

// 重置echarts图表大小
const resizeChart = () => {
  myChart.value.resize();
};

// 设置echarts图表配置
const setOption = (option) => {
  myChart.value.setOption(option);
};

defineExpose({
  createChart,
  disposeEcharts,
});
</script>

<style lang="less" scoped>
.chart_data_preview {
  position: relative;
  width: 100%;
  height: 100%;
  padding-top: 35px;
  box-sizing: border-box;
  .chart_operate {
    position: absolute;
    left: 20px;
    top: 8px;
    cursor: pointer;
  }
  .chart_table_data {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: #0f1318;
    z-index: 10;
    .chart_table_title {
      margin: 16px 0;
      font-size: 16px;
      height: 20px;
    }
    .chart_table {
      height: calc(100% - 36px - 52px);
    }
    .chart_table thead {
      color: @default;
      background-color: rgba(17, 98, 98, 0.75);
    }
  }
  .chart_table_operate {
    display: flex;
    flex-direction: row-reverse;
    align-items: center;
    gap: 20px;
    height: 36px;
    font-size: 12px;
    .chart_table_operate_btn {
      padding: 3px 8px;
      background-color: rgba(8, 134, 146, 1);
      border-radius: 3px;
      color: #fff;
      cursor: pointer;
    }
  }
  td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .tbody {
    overflow-y: auto;
  }
  .tbody::-webkit-scrollbar {
    width: 0px;
  }
}

.chart_box {
  width: 100%;
  height: 100%;
}

.fade-enter-active,
.fade-leave-active {
  transition: all 0.3s;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
  transform: scale(0.6);
}

.fade-enter-to,
.fade-leave-from {
  opacity: 1;
  transform: scale(1);
}
</style>
